home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / graph_alg / _mcmflow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  8.9 KB  |  337 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _mcmflow.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. //------------------------------------------------------------------------------
  17. //
  18. // MIN_COST_MAX_FLOW(G,s,t,cap,cost,flow)
  19. //
  20. // computes a maximal s-t flow of minimal total cost in network (G,cap,cost)
  21. //
  22. // Algorithm: successive shortest path augmentation + capacity scaling
  23. //
  24. // Based on:  J. Edmonds and R. M. Karp: 
  25. //            "Theoretical Improvements in Algorithmic Efficiency for Network 
  26. //            Flow Problems", Journal of the  ACM, Vol. 19, No. 2, 1972
  27. //
  28. //            R.K. Ahuja, T.L. Magnanti, J.B. Orlin: 
  29. //            "Network Flows", Section 10.2, Prentice Hall Publ. Company, 1993
  30. //
  31. //
  32. // S. N"aher  (December 1993)
  33. //------------------------------------------------------------------------------
  34.  
  35. #include <LEDA/graph_alg.h>
  36. #include <LEDA/node_pq.h>
  37.  
  38.  
  39. static node DIJKSTRA_IN_RESIDUAL(const graph& G, node s, int delta, 
  40.                                  const edge_array<num_type>& cost,
  41.                                  const edge_array<num_type>& cap_minus_flow,
  42.                                  const edge_array<num_type>& flow,
  43.                                  const node_array<num_type>& excess,
  44.                                  node_array<num_type>& pi,
  45.                                  node_array<edge>& pred)
  46. {
  47.    /*  Computes a shortest path from node s until a node t with excess <= -delta
  48.        is reached in the delta-residual graph of network G. Edges are traversed
  49.        in both directions using the forall_in/out_edges iteration macros.The 
  50.        residual capacity of an edge e is cap_minus_flow[e] if e is used from 
  51.        source(e) to target(e) and flow[e] otherwise. The reduced cost of an
  52.        edge e = (u,v) is equal to cost[e] + pi[u] - pi[v] if it is used from 
  53.        u and -cost[e] + pi[v] - pi[u] if it is used from v.
  54.  
  55.        precondition: every edge in the delta-residual network has non-negative 
  56.                      reduced cost.
  57.        
  58.        returns t (nil,if there is no path from s to a node with excess<-delta)
  59.  
  60.        and
  61.  
  62.        pred[v] = predecessor edge of v on the shortest path from s to t
  63.  
  64.        pi[v]   = pi'[v] + dist[v] - dist[t], if v is permanently labeled
  65.                  pi'[v],                     if v is temporarily labeled
  66.                  (here pi' is the old potential vector)
  67.  
  68.   */
  69.  
  70.   node_array<num_type> dist(G,MAXINT);
  71.   node_pq<num_type> PQ(G);
  72.   node v;
  73.   edge e;
  74.  
  75.   node t = nil;
  76.  
  77.   node_list perm_labeled; // list of permanently labeled nodes
  78.  
  79.   dist[s] = 0;
  80.   PQ.insert(s,0);
  81.  
  82.   while (!PQ.empty())
  83.   { node u = PQ.del_min();
  84.  
  85.     perm_labeled.append(u);
  86.  
  87.     if (excess[u] <= -delta) 
  88.     { t = u;
  89.       break;
  90.      }
  91.  
  92.     num_type du = dist[u] + pi[u]; 
  93.  
  94.     forall_out_edges(e,u) 
  95.       if (cap_minus_flow[e] >= delta)  // e in delta-residual graph
  96.       { v = target(e);
  97.         num_type c = du - pi[v] + cost[e];
  98.         if (c < dist[v])
  99.         { if (dist[v] == MAXINT) // v has not been reached before
  100.             PQ.insert(v,c);
  101.           else
  102.             PQ.decrease_inf(v,c);
  103.           dist[v] = c;
  104.           pred[v] = e;
  105.          }
  106.        }
  107.  
  108.     forall_in_edges(e,u) 
  109.       if (flow[e] >= delta)  // e in delta-residual graph
  110.       { v = source(e);
  111.         num_type c = du - pi[v] - cost[e];
  112.         if (c < dist[v])
  113.         { if (dist[v] == MAXINT) // v has not been reached before
  114.             PQ.insert(v,c);
  115.           else
  116.             PQ.decrease_inf(v,c);
  117.           dist[v] = c;
  118.           pred[v] = e;
  119.          }
  120.        }
  121.  
  122.    }
  123.  
  124.    if (t != nil) // update potentials of all permanently labeled nodes
  125.    { num_type dt = dist[t];
  126.      forall(v,perm_labeled) pi[v] += dist[v] - dt;
  127.     }
  128.  
  129.    return t;
  130. }
  131.  
  132.  
  133.  
  134. num_type MIN_COST_MAX_FLOW(graph& G, node src, node sink,
  135.                                               const edge_array<num_type>& cap0,
  136.                                               const edge_array<num_type>& cost0,
  137.                                               edge_array<num_type>& flow0)
  138.   double n = G.number_of_nodes();
  139.   double m = G.number_of_edges();
  140.  
  141.   num_type total_flow = 0;               // total flow value (returned)
  142.   int  count = 0;                        // number of augmentations
  143.   node v;
  144.   edge e;
  145.  
  146.   num_type supply = MAX_FLOW(G,src,sink,cap0,flow0);
  147.  
  148.  
  149.   num_type C = 0;  // maximal cost of an s-t path in G
  150.  
  151.   forall_edges(e,G)
  152.   { if (cost0[e] > C)  C = cost0[e];
  153.     if (cost0[e] < -C) C = -cost0[e];
  154.    }
  155.  
  156.   C = C * G.number_of_nodes();
  157.  
  158.  
  159.  
  160.   list<edge> art_edges;  // list of artificial edges (see below)
  161.   list<edge> neg_edges;  // list of negative cost edges
  162.  
  163.   // add artificial edges to guarantee existence of a path of infinite
  164.   // capacity (MAXINT) and huge cost (C) between any pair of nodes  (v,w)
  165.   // with b(v) > 0 and b(w) < 0
  166.    
  167.   //forall_nodes(v,G) 
  168.   //if (v != src) 
  169.   //{ art_edges.append(G.new_edge(v,src));
  170.   //  art_edges.append(G.new_edge(src,v));
  171.   // }
  172.  
  173.   art_edges.append(G.new_edge(src,sink));
  174.  
  175.  
  176.   node_array<num_type> pi(G,0);           // node potential
  177.   node_array<num_type> excess(G,0);       // excess
  178.   node_array<edge>     pred(G,nil);       // predecessor edge on shortest path
  179.   edge_array<num_type> flow(G,0);
  180.   edge_array<num_type> cap(G,0);
  181.   edge_array<num_type> cost(G,0);
  182.   edge_array<num_type> cap_minus_flow(G,0);
  183.  
  184.  
  185.   forall_edges(e,G)
  186.   { cap[e] = cap0[e];
  187.     cost[e] = cost0[e];
  188.     cap_minus_flow[e] = cap[e];
  189.     if (cost[e] < 0) neg_edges.append(e);
  190.    }
  191.  
  192.   forall(e,art_edges)
  193.   { cap[e] = MAXINT;
  194.     cost[e] = C;
  195.     cap_minus_flow[e] = MAXINT;
  196.    }
  197.  
  198.   excess[src]  =  supply;
  199.   excess[sink] = -supply;
  200.  
  201.  
  202.   // eliminate negative cost edges by edge reversals 
  203.   // (Ahuja/Magnanti/Orlin, section 2.4)
  204.  
  205.   forall(e,neg_edges)
  206.   { node u = source(e);
  207.     node v = target(e);
  208.     excess[u] -= cap[e];
  209.     excess[v] += cap[e];
  210.     cost[e] = -cost[e];
  211.     G.rev_edge(e);
  212.   }
  213.  
  214.   int delta = 1;
  215.  
  216.   double delta_max = supply * m/(n*n);  // seems to be a good choice
  217.  
  218.   while (2*delta <= delta_max) delta = 2*delta;
  219.  
  220.   while (delta > 0)  // delta scaling phase
  221.   {
  222.     forall_edges(e,G)  
  223.     { // Saturate all edges entering the delta residual network which have
  224.       // a negative reduced edge cost. Then only the reverse edge (with positive
  225.       // reduced edge cost) will stay in the residual network. 
  226.  
  227.       node u = source(e);
  228.       node v = target(e);
  229.       num_type c = cost[e] + pi[u] - pi[v];
  230.  
  231.       if (cap_minus_flow[e] >= delta && c < 0)
  232.         { excess[v] += cap_minus_flow[e];
  233.           excess[u] -= cap_minus_flow[e];
  234.           flow[e] = cap[e];
  235.           cap_minus_flow[e] = 0;
  236.          }
  237.       else
  238.         if (flow[e] >= delta && c > 0)
  239.         { excess[u] += flow[e];
  240.           excess[v] -= flow[e];
  241.           flow[e] = 0;
  242.           cap_minus_flow[e] = cap[e];
  243.          }
  244.  
  245.      }
  246.  
  247.  
  248.     // As long as there is a node s with excess >= delta compute a minimum
  249.     // cost augmenting path from s to a sink node t with excess <= -delta in 
  250.     // the delta-residual network and augment the flow by at least delta units 
  251.     // along P (if there are nodes with excess > delta and excess < -delta
  252.     // respectively, the existence of P is guaranteed by the artificial edges 
  253.     // inserted at the begining of the algorithm)
  254.  
  255.     node s;
  256.     node t;
  257.   
  258.     forall_nodes(s,G)
  259.     while (excess[s] >= delta)
  260.     { 
  261.       count++;
  262.   
  263.       t = DIJKSTRA_IN_RESIDUAL(G,s,delta,cost,cap_minus_flow,flow,excess,pi,pred);
  264.       if (t == nil) break; // there is no node with excess < -delta
  265.   
  266.       // compute maximal amount f of flow that can be pushed through P
  267.   
  268.       num_type f = excess[s];
  269.   
  270.       v = t; 
  271.       while (v != s)
  272.       { e = pred[v]; 
  273.         num_type rcap;
  274.         if (v==target(e))
  275.            { rcap = cap_minus_flow[e];
  276.              v = source(e);
  277.             }
  278.         else
  279.            { rcap = flow[e];
  280.              v = target(e);
  281.             }
  282.         if (rcap < f) f = rcap;
  283.        }
  284.   
  285.       if (f > -excess[t]) f = -excess[t];
  286.   
  287.   
  288.       // add f units of flow along the augmenting path 
  289.   
  290.       v = t; 
  291.       while (v != s)
  292.       { e = pred[v]; 
  293.         if (v==target(e))
  294.            { flow[e] += f;
  295.              cap_minus_flow[e] -= f;
  296.              v = source(e);
  297.             }
  298.         else
  299.            { flow[e] -= f;
  300.              cap_minus_flow[e] += f;
  301.              v = target(e);
  302.             }
  303.        }
  304.   
  305.        excess[s] -= f;
  306.        excess[t] += f;
  307.   
  308.     } // end of delta-phase
  309.   
  310.    delta /= 2;
  311.   
  312.   } // end of scaling
  313.   
  314.  
  315.  
  316.   // restore negative edges
  317.   forall(e,neg_edges) 
  318.   { flow[e] = cap[e] - flow[e];
  319.     G.rev_edge(e);
  320.    }
  321.  
  322.   // delete artificial edges
  323.   forall(e,art_edges) G.del_edge(e); 
  324.  
  325.   // total flow  = total flow out of the source node
  326.   forall_out_edges(e,src) total_flow += flow[e];
  327.  
  328.   forall_edges(e,G) flow0[e] = flow[e];
  329.  
  330.   //cout << "count = " << count << endl;
  331.  
  332.   return total_flow;
  333. }
  334.  
  335.